# -*- coding: utf-8 -*-
"""
RBAC权限管理API

提供动态权限管理的RESTful接口：
- 角色管理：创建、查询、更新、删除角色
- 权限管理：权限查询、分配、撤销
- 用户权限：用户角色分配、权限查询
- 资源管理：系统资源的动态管理
"""

from typing import List, Dict, Any, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from pydantic import BaseModel, Field
import logging

from ...core.database import get_db
from ...auth.jwt_auth import get_current_active_user
from ...models.rbac import User, Role, Permission, Resource, UserRole, RolePermission
from ...models.rbac import UserStatus, PermissionAction, ResourceType
from ...services.rbac_service import get_permission_manager, PermissionDecorator
from ...core.dto import ResponseDTO, ListResponseDTO

logger = logging.getLogger(__name__)
router = APIRouter()


# ==================== 数据模型 ====================

class RoleCreateRequest(BaseModel):
    """创建角色请求"""
    name: str = Field(..., description="角色名称", max_length=50)
    code: str = Field(..., description="角色编码", max_length=50)
    description: Optional[str] = Field(None, description="角色描述")
    parent_id: Optional[int] = Field(None, description="父角色ID")
    is_active: bool = Field(True, description="是否激活")


class RoleUpdateRequest(BaseModel):
    """更新角色请求"""
    name: Optional[str] = Field(None, description="角色名称", max_length=50)
    description: Optional[str] = Field(None, description="角色描述")
    is_active: Optional[bool] = Field(None, description="是否激活")


class PermissionAssignRequest(BaseModel):
    """权限分配请求"""
    role_id: int = Field(..., description="角色ID")
    permission_ids: List[int] = Field(..., description="权限ID列表")


class UserRoleAssignRequest(BaseModel):
    """用户角色分配请求"""
    user_id: int = Field(..., description="用户ID")
    role_ids: List[int] = Field(..., description="角色ID列表")


class PermissionCheckRequest(BaseModel):
    """权限检查请求"""
    resource: str = Field(..., description="资源标识")
    action: str = Field(..., description="操作类型")
    context: Optional[Dict[str, Any]] = Field(None, description="上下文信息")


# ==================== 角色管理API ====================

@router.get("/roles", response_model=ResponseDTO[List[Dict]], summary="获取角色列表")
@PermissionDecorator.require_permission("system.roles", "read")
async def get_roles(
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user),
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=100, description="每页数量"),
    search: Optional[str] = Query(None, description="搜索关键词")
):
    """获取角色列表"""
    try:
        query = db.query(Role).filter(Role.is_active == True)
        
        if search:
            query = query.filter(
                Role.name.contains(search) | 
                Role.description.contains(search)
            )
        
        total = query.count()
        roles = query.offset((page - 1) * size).limit(size).all()
        
        role_list = []
        for role in roles:
            role_data = {
                "id": role.id,
                "name": role.name,
                "code": role.code,
                "description": role.description,
                "level": role.level,
                "is_active": role.is_active,
                "is_system": role.is_system,
                "created_at": role.created_at.isoformat(),
                "user_count": len(role.user_roles)
            }
            role_list.append(role_data)
        
        return ResponseDTO[List[Dict]](
            success=True,
            message="获取角色列表成功",
            data=role_list,
            total=total,
            page=page,
            size=size
        )
        
    except Exception as e:
        logger.error(f"获取角色列表失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取角色列表失败"
        )


@router.post("/roles", response_model=ResponseDTO[Dict], summary="创建角色")
@PermissionDecorator.require_permission("system.roles", "create")
async def create_role(
    request: RoleCreateRequest,
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user)
):
    """创建新角色"""
    try:
        # 检查角色编码是否已存在
        existing_role = db.query(Role).filter(Role.code == request.code).first()
        if existing_role:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="角色编码已存在"
            )
        
        # 创建角色
        role = Role(
            name=request.name,
            code=request.code,
            description=request.description,
            parent_id=request.parent_id,
            is_active=request.is_active,
            created_by=current_user["user_id"]
        )
        
        db.add(role)
        db.commit()
        db.refresh(role)
        
        role_data = {
            "id": role.id,
            "name": role.name,
            "code": role.code,
            "description": role.description,
            "is_active": role.is_active,
            "created_at": role.created_at.isoformat()
        }
        
        logger.info(f"创建角色成功: {role.name}, 操作人: {current_user['username']}")
        
        return ResponseDTO[Dict](
            success=True,
            message="创建角色成功",
            data=role_data
        )
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"创建角色失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="创建角色失败"
        )


@router.put("/roles/{role_id}", response_model=ResponseDTO[Dict], summary="更新角色")
@PermissionDecorator.require_permission("system.roles", "update")
async def update_role(
    role_id: int,
    request: RoleUpdateRequest,
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user)
):
    """更新角色信息"""
    try:
        role = db.query(Role).filter(Role.id == role_id).first()
        if not role:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )
        
        # 不允许修改系统角色
        if role.is_system:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="系统角色不允许修改"
            )
        
        # 更新字段
        if request.name is not None:
            role.name = request.name
        if request.description is not None:
            role.description = request.description
        if request.is_active is not None:
            role.is_active = request.is_active
        
        role.updated_by = current_user["user_id"]
        
        db.commit()
        db.refresh(role)
        
        # 清除相关用户的权限缓存
        permission_manager = get_permission_manager(db)
        for user_role in role.user_roles:
            permission_manager.invalidate_user_cache(user_role.user_id)
        
        role_data = {
            "id": role.id,
            "name": role.name,
            "code": role.code,
            "description": role.description,
            "is_active": role.is_active,
            "updated_at": role.updated_at.isoformat()
        }
        
        logger.info(f"更新角色成功: {role.name}, 操作人: {current_user['username']}")
        
        return ResponseDTO[Dict](
            success=True,
            message="更新角色成功",
            data=role_data
        )
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"更新角色失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新角色失败"
        )


# ==================== 权限管理API ====================

@router.get("/permissions", response_model=ResponseDTO[List[Dict]], summary="获取权限列表")
@PermissionDecorator.require_permission("system.permissions", "read")
async def get_permissions(
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user),
    resource_id: Optional[int] = Query(None, description="资源ID筛选"),
    action: Optional[str] = Query(None, description="操作类型筛选")
):
    """获取权限列表"""
    try:
        query = db.query(Permission, Resource).join(Resource).filter(Permission.is_active == True)
        
        if resource_id:
            query = query.filter(Permission.resource_id == resource_id)
        
        if action:
            query = query.filter(Permission.action == action)
        
        results = query.all()
        
        permission_list = []
        for permission, resource in results:
            permission_data = {
                "id": permission.id,
                "name": permission.name,
                "code": permission.code,
                "description": permission.description,
                "action": permission.action.value,
                "resource": {
                    "id": resource.id,
                    "name": resource.name,
                    "code": resource.code,
                    "type": resource.type.value,
                    "module": resource.module
                }
            }
            permission_list.append(permission_data)
        
        return ResponseDTO[List[Dict]](
            success=True,
            message="获取权限列表成功",
            data=permission_list
        )
        
    except Exception as e:
        logger.error(f"获取权限列表失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取权限列表失败"
        )


@router.post("/roles/{role_id}/permissions", response_model=ResponseDTO[Dict], summary="分配权限给角色")
@PermissionDecorator.require_permission("system.roles", "manage")
async def assign_permissions_to_role(
    role_id: int,
    request: PermissionAssignRequest,
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user)
):
    """为角色分配权限"""
    try:
        # 验证角色存在
        role = db.query(Role).filter(Role.id == role_id).first()
        if not role:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )
        
        # 清除现有权限
        db.query(RolePermission).filter(RolePermission.role_id == role_id).delete()
        
        # 分配新权限
        assigned_count = 0
        for permission_id in request.permission_ids:
            # 验证权限存在
            permission = db.query(Permission).filter(Permission.id == permission_id).first()
            if permission:
                role_permission = RolePermission(
                    role_id=role_id,
                    permission_id=permission_id,
                    assigned_by=current_user["user_id"]
                )
                db.add(role_permission)
                assigned_count += 1
        
        db.commit()
        
        # 清除相关用户的权限缓存
        permission_manager = get_permission_manager(db)
        for user_role in role.user_roles:
            permission_manager.invalidate_user_cache(user_role.user_id)
        
        logger.info(f"角色权限分配成功: 角色{role.name}, 权限数量{assigned_count}, 操作人: {current_user['username']}")
        
        return ResponseDTO[Dict](
            success=True,
            message="权限分配成功",
            data={
                "role_id": role_id,
                "assigned_permissions": assigned_count
            }
        )
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"权限分配失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="权限分配失败"
        )


# ==================== 用户权限API ====================

@router.get("/users/{user_id}/permissions", response_model=ResponseDTO[Dict], summary="获取用户权限")
@PermissionDecorator.require_permission("system.users", "read")
async def get_user_permissions(
    user_id: int,
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user)
):
    """获取用户的所有权限"""
    try:
        permission_manager = get_permission_manager(db)
        user_permissions = permission_manager.get_user_permissions(user_id)
        
        # 获取用户的角色信息
        user_roles = (
            db.query(Role)
            .join(UserRole)
            .filter(UserRole.user_id == user_id, UserRole.is_active == True)
            .all()
        )
        
        # 获取可访问的资源
        accessible_resources = permission_manager.get_user_accessible_resources(user_id)
        
        permission_data = {
            "user_id": user_id,
            "permissions": list(user_permissions),
            "roles": [{"id": role.id, "name": role.name, "code": role.code} for role in user_roles],
            "accessible_resources": accessible_resources
        }
        
        return ResponseDTO[Dict](
            success=True,
            message="获取用户权限成功",
            data=permission_data
        )
        
    except Exception as e:
        logger.error(f"获取用户权限失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取用户权限失败"
        )


@router.post("/users/{user_id}/roles", response_model=ResponseDTO[Dict], summary="分配角色给用户")
@PermissionDecorator.require_permission("system.users", "manage")
async def assign_roles_to_user(
    user_id: int,
    request: UserRoleAssignRequest,
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user)
):
    """为用户分配角色"""
    try:
        # 验证用户存在
        user = db.query(User).filter(User.id == user_id).first()
        if not user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        # 清除现有角色
        db.query(UserRole).filter(UserRole.user_id == user_id).delete()
        
        # 分配新角色
        assigned_count = 0
        for role_id in request.role_ids:
            # 验证角色存在
            role = db.query(Role).filter(Role.id == role_id).first()
            if role:
                user_role = UserRole(
                    user_id=user_id,
                    role_id=role_id,
                    assigned_by=current_user["user_id"]
                )
                db.add(user_role)
                assigned_count += 1
        
        db.commit()
        
        # 清除用户权限缓存
        permission_manager = get_permission_manager(db)
        permission_manager.invalidate_user_cache(user_id)
        
        logger.info(f"用户角色分配成功: 用户{user.username}, 角色数量{assigned_count}, 操作人: {current_user['username']}")
        
        return ResponseDTO[Dict](
            success=True,
            message="角色分配成功",
            data={
                "user_id": user_id,
                "assigned_roles": assigned_count
            }
        )
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"角色分配失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="角色分配失败"
        )


@router.post("/permissions/check", response_model=ResponseDTO[Dict], summary="检查权限")
async def check_permission(
    request: PermissionCheckRequest,
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user)
):
    """检查当前用户是否有特定权限"""
    try:
        permission_manager = get_permission_manager(db)
        has_permission = permission_manager.check_permission(
            current_user["user_id"],
            request.resource,
            request.action,
            request.context
        )
        
        return ResponseDTO[Dict](
            success=True,
            message="权限检查完成",
            data={
                "has_permission": has_permission,
                "resource": request.resource,
                "action": request.action
            }
        )
        
    except Exception as e:
        logger.error(f"权限检查失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="权限检查失败"
        )


# ==================== 资源管理API ====================

@router.get("/resources", response_model=ResponseDTO[List[Dict]], summary="获取资源列表")
@PermissionDecorator.require_permission("system.resources", "read")
async def get_resources(
    db: Session = Depends(get_db),
    current_user: Dict[str, Any] = Depends(get_current_active_user),
    type: Optional[str] = Query(None, description="资源类型筛选"),
    module: Optional[str] = Query(None, description="模块筛选")
):
    """获取系统资源列表"""
    try:
        query = db.query(Resource).filter(Resource.is_active == True)
        
        if type:
            query = query.filter(Resource.type == type)
        
        if module:
            query = query.filter(Resource.module == module)
        
        resources = query.all()
        
        resource_list = []
        for resource in resources:
            resource_data = {
                "id": resource.id,
                "name": resource.name,
                "code": resource.code,
                "type": resource.type.value,
                "module": resource.module,
                "path": resource.path,
                "level": resource.level,
                "is_active": resource.is_active
            }
            resource_list.append(resource_data)
        
        return ResponseDTO[List[Dict]](
            success=True,
            message="获取资源列表成功",
            data=resource_list
        )
        
    except Exception as e:
        logger.error(f"获取资源列表失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取资源列表失败"
        )